package cn.seaboot.admin.reverse.manager;

import cn.seaboot.admin.reverse.bean.CodeGroup;
import cn.seaboot.admin.reverse.bean.CodeTemplate;
import cn.seaboot.flake.entity.MappingTable;
import cn.seaboot.admin.reverse.service.CodeGroupService;
import cn.seaboot.admin.reverse.service.CodeTplService;
import cn.seaboot.admin.reverse.service.MappingService;
import cn.seaboot.commons.core.FastJsonUtils;
import cn.seaboot.commons.file.Beetles;
import cn.seaboot.commons.file.FileUtils;
import cn.seaboot.commons.file.IOUtils;
import com.alibaba.fastjson2.JSONObject;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;

/**
 * @author Mr.css
 * @version 2021-12-10 11:28
 */
@Service
public class JavaCodeBuilder {

    @Resource
    private CodeTplService tplService;

    @Resource
    private MappingService mappingService;

    @Resource
    private CodeGroupService codeGroupService;

    /**
     * 生成代码
     *
     * @param id         模版ID
     * @param groupName  代码配置分组
     * @param schemaName 数据库名称
     * @param tableName  表名
     * @param escape     是否转义
     * @return 代码
     * @throws IOException       -
     * @throws TemplateException -
     */
    public String genCode(String id, String groupName, String schemaName, String tableName, Boolean escape) throws IOException, TemplateException {
        CodeTemplate tpl = tplService.queryById(id);
        CodeGroup codeGroup = this.codeGroupService.queryById(groupName, id);

        Map<String, Object> attach = FastJsonUtils.toJSONObject(codeGroup.getAttach());

        MappingTable mappingTable = mappingService.queryMappingTable(schemaName, tableName);
        mappingTable.setAttach(attach);

        JSONObject params = this.convertToMap(mappingTable);

        String res = Beetles.process(tpl.getTplContent(), params);
        if (escape == Boolean.TRUE) {
            // 进行数据转义，防止前端页面处理出错
            return StringUtils
                    .replaceEach(res, new String[]{">", "<", "&", "\""}, new String[]{"&gt;", "&lt;", "&amp;", "&quot;"});
        } else {
            return res;
        }
    }

    /**
     * 生成代码，最终直接写入到文件
     *
     * @param id         模版ID
     * @param groupName  代码配置分组
     * @param schemaName 数据库名称
     * @param tableName  表名
     * @param escape     是否转义
     * @throws IOException       -
     * @throws TemplateException -
     */
    public void writeCode(String id, String groupName, String schemaName, String tableName, Boolean escape) throws IOException, TemplateException {
        CodeTemplate tpl = tplService.queryById(id);
        CodeGroup codeGroup = this.codeGroupService.queryById(groupName, id);

        Map<String, Object> attach = FastJsonUtils.toJSONObject(codeGroup.getAttach());

        MappingTable mappingTable = mappingService.queryMappingTable(schemaName, tableName);
        mappingTable.setAttach(attach);

        JSONObject params = this.convertToMap(mappingTable);

        String code = Beetles.process(tpl.getTplContent(), params);
        String fileName = Beetles.process(tpl.getFileNameTpl(), params);

        // 根据配置的包名，直接生成文件
        File root = new File(codeGroup.getSavePath());
        File file = FileUtils.file(new File(root, fileName));
        try (OutputStream os = IOUtils.openFileOutputStream(file)) {
            os.write(code.getBytes());
        }
    }


    private JSONObject convertToMap(MappingTable table){
        // 需要将对象转换成 map
        return FastJsonUtils.toJSONObject(table);
    }
}
